package cn.jsu.oj.dispatchServer.handle.handles;

import cn.jsu.oj.dispatchServer.handle.CommandPack;
import cn.jsu.oj.dispatchServer.init.ClientInitVector;
import cn.jsu.oj.dispatchServer.mapper.ResultMapper;
import cn.jsu.oj.dispatchServer.mapper.TopicSetMapper;
import cn.jsu.oj.dispatchServer.net.DispatchServerHandle;
import cn.jsu.oj.dispatchServer.parsing.HandleType;
import cn.jsu.oj.dispatchServer.pojo.JudgeResult;
import cn.jsu.oj.dispatchServer.pojo.StorageCmdInfo;
import cn.jsu.oj.dispatchServer.pojo.TaskInfo;
import cn.jsu.oj.dispatchServer.pojo.dto.TestChangeScore;
import cn.jsu.oj.dispatchServer.pojo.dto.TopicSetTopicMaxScore;
import cn.jsu.oj.dispatchServer.resource.Resource;
import cn.jsu.oj.dispatchServer.utils.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Map;

/**
 * @author ahtonc
 * @date 2021/4/6
 */
@Slf4j
@HandleType(type = 8)
public class JudgeResultHandle implements Handle {

    ResultMapper resultMapper = SpringUtil.getBean(ResultMapper.class);

    TopicSetMapper topicSetMapper = SpringUtil.getBean(TopicSetMapper.class);

    @Override
    public CommandPack<?> handle(CommandPack<?> pack) {
        JudgeResult result = (JudgeResult) pack.getData();
        updateJudgeResult(result);
        log.warn("收到结果 任务大队列任务数目:" + Resource.taskBigQueue.size());
        Map<Long, TaskInfo> taskMap = Resource.storeTaskMap.get(pack.getIp());
        if (taskMap != null) {
            //删除暂存任务
            taskMap.remove(result.getSerialNumber());
        }

        //发送确认存储信息
        ClientInitVector vector = DispatchServerHandle.vectorMap.get(pack.getIpAndPort());
        StorageCmdInfo storageCmdInfo = new StorageCmdInfo();
        storageCmdInfo.setSerialNumber(result.getSerialNumber());
        try {
            vector.getChannel().writeAndFlush(storageCmdInfo.serialize());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    //将此次任务的信息更新到各个表里
    private void updateJudgeResult(JudgeResult judgeResult) {
        int maxScore = 0, maxRunTime = 0, maxRunMemory = 0, score;
        int number = judgeResult.getPointResult().length;
        long serialNumber = judgeResult.getSerialNumber();
        int[] runTime = judgeResult.getRunTime();
        int[] runMemory = judgeResult.getRunMemory();
        byte[] pointResult = judgeResult.getPointResult();
        //查看试卷内对应题目的分数
        List<TestChangeScore> testChangeScores = resultMapper.testChangeScores(judgeResult.getSerialNumber());
        //如果试卷内没有对应题目分数，说明是老师提交测试用例的测试，去测试点表中拿分数
        if (testChangeScores.size() == 0) {
            testChangeScores = resultMapper.testPointScores(judgeResult.getSerialNumber());
        }

        //将测试点结果保存在测试点结果表

        if (pointResult[0] == 2) {
            runMemory = runTime = new int[pointResult.length];
        }

        for (int i = 0; i < number; i++) {
            score = 0;
            if (pointResult[i] == 1) {
                score = testChangeScores.get(i).getTestPointScore();
                maxScore += score;
            } else if (pointResult[0] == 2) {
                pointResult[i] = 2;
            }
            maxRunMemory = Math.max(maxRunMemory, runMemory[i]);
            maxRunTime = Math.max(maxRunTime, runTime[i]);
            resultMapper.insertJudgePointResult(i, serialNumber, runTime[i],
                    runMemory[i], pointResult[i], score);
        }
        //将结果保存在编程题题目提交表
        resultMapper.updateSubmitTopic(serialNumber, maxRunTime, maxRunMemory,
                judgeResult.getCompilationInformation(), maxScore);

        //更新题目集题目分数最大值
        TopicSetTopicMaxScore sc = topicSetMapper.getUserIdAadTopicSetIdBySerialNumber(judgeResult.getSerialNumber());
        TopicSetTopicMaxScore topicSetTopicMaxScore = topicSetMapper.getTopicSetTopicMaxScore(sc.getTopicSetId(),
                sc.getTopicId(), sc.getTopicTypeId(), sc.getAccountId());

        if (topicSetTopicMaxScore == null) {
            sc.setTopicMaxScore(0);
            topicSetMapper.insertTopicSetTopicMaxScore(sc);
        } else {
            //最大分数maxScore
            if (topicSetTopicMaxScore.getTopicMaxScore() < maxScore) {
                topicSetTopicMaxScore.setTopicMaxScore(maxScore);
                topicSetMapper.updateTopicSetTopicMaxScore(topicSetTopicMaxScore);
            }
        }
    }
}
